package cc.rengu.igas.opms.core.service.trans.gateway;

import cc.rengu.igas.channel.upgw.facade.bean.RiskInfo;
import cc.rengu.igas.channel.upgw.facade.bean.TermInfo;
import cc.rengu.igas.channel.upgw.facade.bean.UpgwMchntInfo;
import cc.rengu.igas.channel.upgw.facade.request.UpgwEnterpriseGatewayPaymentRequest;
import cc.rengu.igas.channel.upgw.facade.request.UpgwPersonalGatewayPaymentRequest;
import cc.rengu.igas.channel.upgw.facade.response.UpgwEnterpriseGatewayPaymentResponse;
import cc.rengu.igas.channel.upgw.facade.response.UpgwPersonalGatewayPaymentResponse;
import cc.rengu.igas.momp.facade.base.Header;
import cc.rengu.igas.momp.facade.bean.PaymentOrderCouponInfoBean;
import cc.rengu.igas.momp.facade.bean.PaymentOrderDetailBean;
import cc.rengu.igas.momp.facade.request.ComboPaymentRequest;
import cc.rengu.igas.momp.facade.request.ComboPaymentReversalRequest;
import cc.rengu.igas.momp.facade.response.ComboPaymentResponse;
import cc.rengu.igas.momp.facade.result.Result;
import cc.rengu.igas.opms.common.constant.OpmsParamConstant;
import cc.rengu.igas.opms.common.constant.OpmsTreeNodeConstant;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.core.service.base.PayService;
import cc.rengu.igas.opms.facade.bean.EncryptAssInfo;
import cc.rengu.igas.opms.facade.request.CupsGatewayPayRequest;
import cc.rengu.igas.opms.facade.response.CupsGatewayPayResponse;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.common.constant.ShareTreeNodeConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.core.model.MchntAcctInfo;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.model.PlatMchntInfo;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.jradp.asynnotify.AsynNotify;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderDetailMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderDetailMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 银联新网银支付 个人网银支付和企业网银支付通用
 */
public class CupsGatewayPayService extends PayService implements TransCustomImpl {

    @Override
    protected Object bizBeforeCust() throws Exception {
        CupsGatewayPayRequest cupsGatewayPayRequest = new CupsGatewayPayRequest();
        ConvertUtil.convertOutput(cupsGatewayPayRequest);
        return cupsGatewayPayRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {

        CupsGatewayPayRequest cupsGatewayPayRequest = (CupsGatewayPayRequest) request;
        String instId = cupsGatewayPayRequest.getHeader().getInstId();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        List<ChannelCallCfg> mompTxnNumList = txnInfo.getChannelCallCfgList().stream().filter(channelCallCfg -> ChannelEnum.MOMP.getChannelType().equals(channelCallCfg.getCallChannelId())).collect(Collectors.toList());
        List<ChannelCallCfg> esbTxnNumList = txnInfo.getChannelCallCfgList().stream().filter(channelCallCfg -> ChannelEnum.ESB.getChannelType().equals(channelCallCfg.getCallChannelId())).collect(Collectors.toList());

        //校验订单信息
        OrderService orderService = new OrderServiceImpl();
        OrderInfo orderInfo = orderService.selectOrderInfoByUserOrderId(instId, cupsGatewayPayRequest.getUserOrderId());
        if (null == orderInfo) {
            rglog.error("订单信息不存在!");
            throw new BizException(RespCodeEnum.ORDER_NOEXIT.getRespCode(), RespCodeEnum.ORDER_NOEXIT.getRespDesc());
        }
        UserOrderInfo userOrderInfo = orderInfo.getUserOrderInfo();
        List<MchntOrderInfo> mchntOrderInfoList = orderInfo.getMchntOrderInfoList();

        //购买卡券的不支持使用优惠券
        boolean isCouponTrans = null != cupsGatewayPayRequest.getCouponInfo() && !StringUtil.isEmptyOrNull(cupsGatewayPayRequest.getCouponInfo().getDiscountId());
        boolean isBuyCouponTrans = false;
        if ("00".equals(mchntOrderInfoList.get(0).getBizSceneType()) || "02".equals(mchntOrderInfoList.get(0).getBizSceneType())) {
            isBuyCouponTrans = true;
        }
        if (isCouponTrans && isBuyCouponTrans) {
            rglog.info("购买卡券的交易不支持使用优惠券");
            throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
        }

        //转换商户订单
        convertMchntOrder(mchntOrderInfoList, cupsGatewayPayRequest, isCouponTrans);

        //调用营销获取优惠 非购买卡券且上传了userId的交易才调用营销接口
        if (!isBuyCouponTrans && !StringUtil.isEmptyOrNull(cupsGatewayPayRequest.getUserId())) {
            rglog.info("非购买卡券且用户userId已经上传，调用营销获取用户的营销....");
            PayOrderInfo mompPayOrderInfo = registMompOrderInfo(userOrderInfo, mompTxnNumList.get(0));
            if (null == mompPayOrderInfo) {
                updateOrderFail(userOrderInfo, mchntOrderInfoList, null);
                throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
            }
            xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.PAY_ORDER_INFO, mompPayOrderInfo);
            Result<ComboPaymentResponse> comboPaymentResponseResult = callMompPayServcie(cupsGatewayPayRequest, mompTxnNumList.get(0), isCouponTrans, userOrderInfo, mchntOrderInfoList);
            //解析营销调用结果
            analysisMompResult(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo, comboPaymentResponseResult, mompTxnNumList.get(1), isCouponTrans, cupsGatewayPayRequest);
        } else {
            userOrderInfo.setRealPayAmt(userOrderInfo.getNeedPayAmt());
        }

        /*更新商户订单明细表*/
        List<MchntOrderDetail> mchntOrderDetailList = new ArrayList<>();
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            MchntOrderDetailMapper mchntOrderDetailMapper = new MchntOrderDetailMapperImpl();
            List<MchntOrderDetail> oneMchntOrderDetailList = mchntOrderDetailMapper.selectMchntOrderDetailByMchntOrderId(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo(), mchntOrderInfo.getMchntOrderId());
            if (!CollectionUtils.isEmpty(oneMchntOrderDetailList)) {
                for (MchntOrderDetail mchntOrderDetail : oneMchntOrderDetailList) {
                    mchntOrderDetail.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
                }
                mchntOrderDetailList.addAll(oneMchntOrderDetailList);
            }
        }
        if (!CollectionUtils.isEmpty(mchntOrderDetailList)) {
            orderService.updateOrderInfo(null, null, mchntOrderDetailList, null);
        }

        //更新用户订单和商户订单
        if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList)) {
            rglog.error("更新订单信息失败");
            throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
        }

        //区分个人网银和企业网银分别调用ESB获取网银转发报文
        rglog.debug("根据业务种类:<{}>,区分个人网银-00还是企业网银-01", cupsGatewayPayRequest.getHeader().getBizType());
        CupsGatewayPayResponse cupsGatewayPayResponse;
        if ("00".equals(cupsGatewayPayRequest.getHeader().getBizType())) {

            //登记网关支付订单信息
            PayOrderInfo personPayOrderInfo = registPayOrderInfo(cupsGatewayPayRequest, userOrderInfo, esbTxnNumList.get(0));
            if (null == personPayOrderInfo) {
                updateOrderFail(userOrderInfo, mchntOrderInfoList, null);
                mompRevsal(mompTxnNumList.get(1));
                throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
            }
            //发送个人网关支付请求报文
            UpgwPersonalGatewayPaymentResponse upgwPersonalResponse = cupsGatewayPersonalPay(cupsGatewayPayRequest, userOrderInfo, personPayOrderInfo, mchntOrderInfoList, esbTxnNumList.get(0), mompTxnNumList.get(1));
            //todo 测试网银退款注释
            rglog.debug("当前线程休眠30S开始....");
            Thread.sleep(30000);
            rglog.debug("当前线程休眠30S结束....");
            //组响应信息
            cupsGatewayPayResponse = analysisUpgwPersonalResponse(upgwPersonalResponse);
        } else if ("01".equals(cupsGatewayPayRequest.getHeader().getBizType())) {

            //登记网关支付订单信息
            PayOrderInfo enterprisePayOrderInfo = registPayOrderInfo(cupsGatewayPayRequest, userOrderInfo, esbTxnNumList.get(1));
            if (null == enterprisePayOrderInfo) {
                updateOrderFail(userOrderInfo, mchntOrderInfoList, null);
                mompRevsal(mompTxnNumList.get(1));
                throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
            }
            //发送企业网关支付请求报文
            UpgwEnterpriseGatewayPaymentResponse upgwEnterpriseResponse = cupsGatewayEnterprisePay(cupsGatewayPayRequest, userOrderInfo, enterprisePayOrderInfo, mchntOrderInfoList, esbTxnNumList.get(1), mompTxnNumList.get(1));
            //组响应信息
            cupsGatewayPayResponse = analysisUpgwEnterpriseResponse(upgwEnterpriseResponse);
        } else {

            rglog.info("不识别的业务类型:<{}>", cupsGatewayPayRequest.getHeader().getBizType());
            updateOrderFail(userOrderInfo, mchntOrderInfoList, null);
            mompRevsal(mompTxnNumList.get(1));
            throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
        }

        /*异步调用订单查证接口*/
        GlobalTransUtil.setCacheValue(TransCacheConstant.USER_ORDER_INFO, userOrderInfo);
        GlobalTransUtil.setCacheValue(TransCacheConstant.MCHNT_ORDER_INFO_LIST, mchntOrderInfoList);
        AsynNotify asynNotify = new AsynNotify();
        int iReturnCode = asynNotify.transactionNotice(ShareServiceConstant.ASYN_PAYORDERSTATUS_QUERY_SERVICE, 5, AsynNotify.GAP_SAME, 60 * 1000);
        if (iReturnCode != 0) {
            rglog.error("异步调起全渠道交易状态查询失败");
        }

        //组响应信息
        BizResponse<CupsGatewayPayResponse> bizResponse = new BizResponse<>();
        bizResponse.setResult(cupsGatewayPayResponse);
        bizResponse.setRspSysId(AppParamConstant.IGAS);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        CupsGatewayPayResponse cupsGatewayPayResponse = (CupsGatewayPayResponse) bizResponse.getResult();
        ConvertUtil.convertInput(cupsGatewayPayResponse);
    }

    /**
     * 营销冲销
     *
     * @param channelCallCfg 营销冲销通道服务调用配置
     * @throws Exception 异常
     */
    private void mompRevsal(ChannelCallCfg channelCallCfg) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        if (xmlTreeUtil.isExist("discountFlag") && AppParamConstant.YES.equals(xmlTreeUtil.getXmlTreeStringValue("discountFlag"))) {

            ComboPaymentRequest comboPaymentRequest = (ComboPaymentRequest) xmlTreeUtil.getXmlTreeObjectValue("comboPaymentRequest", ComboPaymentRequest.class);
            Header header = comboPaymentRequest.getHeader();
            ComboPaymentReversalRequest comboPaymentRevsalRequest = new ComboPaymentReversalRequest();
            comboPaymentRevsalRequest.setOrigTraceNo(header.getTraceNo());
            header.setTxnNum(channelCallCfg.getCallChannelTxn());
            header.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
            comboPaymentRevsalRequest.setHeader(header);
            DubboServiceImpl dubboService = new DubboServiceImpl();
            int iReturnCode = dubboService.asynCallDubboService(OpmsParamConstant.DUBBO_MOMP_PAYMENT_SERVICE, "comboPaymentRevsal", comboPaymentRevsalRequest, "AsynComboPaymentRevsalService");
            if (iReturnCode != 0) {
                rglog.warn("异步营销冲正服务注册失败！");
            }
        }
    }

    /**
     * 交易商户订单表 校验交易权限/商户限额/商户订单初始化
     * 不计算商户手续费,交易成功后得到用户支付卡类型再计算商户手续费
     *
     * @param mchntOrderInfoList 商户订单
     * @param request            支付请求
     * @throws Exception 异常
     */
    private void convertMchntOrder(List<MchntOrderInfo> mchntOrderInfoList, CupsGatewayPayRequest request, boolean isCouponTrans) throws Exception {

        //商户订单初始化
        MchntService mchntService = new MchntServiceImpl();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        boolean surpCreditAcct = true;
        boolean surpDebitAcct = true;
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            MchntInfo mchntInfo = mchntService.getMchntInfo(request.getHeader().getInstId(), mchntOrderInfo.getMchntNo());
            if (null == mchntInfo) {
                rglog.error("查询商户基本信息失败<{}>", mchntOrderInfo.getMchntNo());
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            /*交易权限检查*/
            boolean checkResult = mchntService.checkMchntAuth(request.getHeader().getInstId(), mchntOrderInfo.getMchntNo(), null, request.getHeader().getTxnNum(), request.getHeader().getBizType(), AcctTypeEnum.ALL.getAcctType());
            if (!checkResult) {
                rglog.error("商户<{}>无此交易权限!", mchntOrderInfo.getMchntNo());
                throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
            }
            /*商户限额处理,判断交易是否支持借记卡和贷记卡*/
            int limitFlag = mchntService.checkMchntTransLimit(request.getHeader().getInstId(), mchntOrderInfo.getRealSettleAmt(), LimitAcctTypeEnum.ALL, mchntOrderInfo.getMchntNo(), null, request.getHeader().getTxnNum());
            if (2 == limitFlag) {
                throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
            } else if (1 == limitFlag) {
                surpCreditAcct = false;
            } else if (3 == limitFlag) {
                surpDebitAcct = false;
            }

            //商户订单初始化
            mchntOrderInfo.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
            mchntOrderInfo.setTxnNum(request.getHeader().getTxnNum());
            mchntOrderInfo.setBizType(request.getHeader().getBizType());
            mchntOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
            mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            mchntOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            mchntOrderInfo.setMchntDiscountFee("0.00");
            mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            /*判断是否独立维护资料的门店*/
            if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                mchntOrderInfo.setChainMchntNo(mchntInfo.getChainMchntNo());
            }
            //判断是否实时清算,使用优惠券的交易不实时清算
            if (isCouponTrans) {
                mchntOrderInfo.setRealSettleFlag(AppParamConstant.NO);
            } else {
                String realSettleFlag = mchntService.getRealSettleFlag(mchntInfo.getMchntNo(), txnInfo.getSrcTxnAuthCfg().getBizProdCode(), mchntOrderInfo.getBizSceneType(), mchntOrderInfo.getRealSettleAmt());
                mchntOrderInfo.setRealSettleFlag(realSettleFlag);
                if (AppParamConstant.YES.equals(mchntOrderInfo.getRealSettleFlag())) {
                    mchntOrderInfo.setRealSettleType("99");
                }
            }
        }

        /*合并订单支付，不能合并特殊费率跟非特殊费率，不能合并d0清算跟非d0清算*/
        if (mchntOrderInfoList.size() > 1) {
            List<MchntOrderInfo> mchntOrderInfoSpFeeList = mchntOrderInfoList.stream().filter(item -> "0".equals(item.getFeeInputMode())).collect(Collectors.toList());
            if (!mchntOrderInfoSpFeeList.isEmpty() && mchntOrderInfoSpFeeList.size() != mchntOrderInfoList.size()) {
                rglog.error("合并订单中存在特殊费率跟非特殊费率的订单，拒绝交易");
                throw new BizException(RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespCode(), RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespDesc());
            }
            List<MchntOrderInfo> mchntOrderInfoD0List = mchntOrderInfoList.stream().filter(item -> AppParamConstant.YES.equals(item.getRealSettleFlag())).collect(Collectors.toList());
            if (!mchntOrderInfoD0List.isEmpty() && mchntOrderInfoD0List.size() != mchntOrderInfoList.size()) {
                rglog.error("合并订单中存在d0清算跟非d0清算的订单，拒绝交易");
                throw new BizException(RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespCode(), RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespDesc());
            }
        }

        /*
         * 判断限定的账户类型
         * 借贷记卡都支持     - 00 混合账户类型
         * 支持借记不支持贷记 - 01 借记账户类型
         * 支持贷记不支持借记 - 02 贷记账户类型
         */
        if (!surpCreditAcct && !surpDebitAcct) {
            rglog.info("当前订单借贷记卡都不支持");
            throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
        } else if (surpCreditAcct && surpDebitAcct) {
            xmlTreeUtil.setXmlTreeStringValue("LmtAcctTpCd", "00");
        } else {
            if (surpDebitAcct) {
                xmlTreeUtil.setXmlTreeStringValue("LmtAcctTpCd", "01");
            } else {
                xmlTreeUtil.setXmlTreeStringValue("LmtAcctTpCd", "02");
            }
        }
    }

    /**
     * 登记营销支付订单表
     *
     * @param userOrderInfo  用户订单
     * @param channelCallCfg 营销合并支付通道服务调用配置
     * @return 营销支付订单
     * @throws Exception 异常
     */
    private PayOrderInfo registMompOrderInfo(UserOrderInfo userOrderInfo, ChannelCallCfg channelCallCfg) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        payOrderInfo.setTxnTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        payOrderInfo.setBizType(channelCallCfg.getBizType());
        payOrderInfo.setTxnNum(channelCallCfg.getTxnNum());
        payOrderInfo.setRealPayAmt(userOrderInfo.getNeedPayAmt());
        payOrderInfo.setPayType(PayTypeEnum.OTHER.getPayType());
        payOrderInfo.setPayerAcctType(AcctTypeEnum.COUPON.getAcctType());
        payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        payOrderInfo.setBizStatus(BizStatusEnum.INIT.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        OrderService orderService = new OrderServiceImpl();
        if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
            rglog.warn("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        }

        rglog.debug("登记支付订单表成功,payOrderInfo:<{}>", JSON.toJSONString(payOrderInfo));
        return payOrderInfo;
    }

    /**
     * 更新订单为失败
     *
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @param payOrderInfo       支付订单
     * @throws Exception 异常信息
     */
    private void updateOrderFail(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo) throws Exception {
        OrderService orderService = new OrderServiceImpl();
        String currentDateTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
        //更新用户订单表/商户订单表状态为失败
        userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
        userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
        userOrderInfo.setUpdateTime(currentDateTime);
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            mchntOrderInfo.setUpdateTime(currentDateTime);
        }
        if (null == payOrderInfo) {
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, null)) {
                rglog.warn("更新用户订单/商户订单信息失败");
            } else {
                rglog.debug("更新用户订单/商户订单信息成功");
            }
        } else {
            payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfo.setUpdateTime(currentDateTime);
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                rglog.warn("更新用户订单/商户订单信息失败");
            } else {
                rglog.debug("更新用户订单/商户订单信息成功");
            }
        }
    }

    /**
     * 调用营销合并支付
     *
     * @param request            请求体
     * @param mompChannelCallCfg 营销合并支付通道服务调用配置
     * @param isCouponTrans      是否参与营销
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @return 合并支付调用结果
     * @throws Exception 异常
     */
    private Result<ComboPaymentResponse> callMompPayServcie(CupsGatewayPayRequest request, ChannelCallCfg mompChannelCallCfg, boolean isCouponTrans,
                                                            UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.NO);

        //获取营销产品编码,若营销产品编码未配置则判断用户是否使用卡劵未使用卡劵时交易可以继续往下进行
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(request.getHeader().getInstId(), OpmsParamConstant.MOMP_PROD_CODE,
                request.getHeader().getTxnNum() + request.getHeader().getBizType() + AcctTypeEnum.ALL.getAcctType());
        if (sysParam == null) {
            rglog.error("根据交易码<{}>、业务细分<{}>转换营销产品编码失败", request.getHeader().getTxnNum(), request.getHeader().getBizType());
            return null;
        }

        //请求头
        Header header = new Header();
        header.setInstId(request.getHeader().getInstId());
        header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setBizType(OpmsParamConstant.DUBBO_DEFAULT_BIZ_TYPE);
        header.setVersion("1.0.0");
        header.setTxnNum(mompChannelCallCfg.getCallChannelTxn());
        header.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + mompChannelCallCfg.getCallIndex());
        header.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        header.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        //请求体
        ComboPaymentRequest comboPaymentRequest = new ComboPaymentRequest();
        ConvertUtil.convertOutput(comboPaymentRequest);
        comboPaymentRequest.setHeader(header);
        UserInfo userInfo = JSON.parseObject(RedisUtil.hashGet(request.getHeader().getSession(), request.getHeader().getInstId() + request.getUserId()), UserInfo.class);
        if (null != userInfo) {
            comboPaymentRequest.setUserId(xmlTreeUtil.getXmlTreeStringValue(userInfo.getMobileNo()));
        }
        comboPaymentRequest.setBizProdCode(sysParam.getParamValue());
        comboPaymentRequest.setMchntOrderId(request.getUserOrderId());
        comboPaymentRequest.setTransAmt(userOrderInfo.getNeedPayAmt());
        List<PaymentOrderDetailBean> orderDetailList = new ArrayList<>();
        convertOrderDetail(orderDetailList, mchntOrderInfoList);
        comboPaymentRequest.setOrderDetailList(orderDetailList);
        if (isCouponTrans) {
            List<PaymentOrderCouponInfoBean> couponInfoList = new ArrayList<>();
            PaymentOrderCouponInfoBean paymentOrderCouponInfoBean = new PaymentOrderCouponInfoBean();
            paymentOrderCouponInfoBean.setCouponNo(request.getCouponInfo().getDiscountId());
            couponInfoList.add(paymentOrderCouponInfoBean);
            comboPaymentRequest.setCouponInfoList(couponInfoList);
        }
        xmlTreeUtil.setXmlTreeObjectValue("comboPaymentRequest", comboPaymentRequest);
        rglog.debug("营销优惠试算请求:<{}>", JSON.toJSONString(comboPaymentRequest));

        /*调用营销接口进行优惠试算*/
        try {
            DubboService dubboService = new DubboServiceImpl();
            return (Result<ComboPaymentResponse>) dubboService.callDubboService(OpmsParamConstant.DUBBO_MOMP_PAYMENT_SERVICE, "comboPayment", comboPaymentRequest);
        } catch (Exception e) {
            rglog.error("调用营销合并支付接口异常:<{}>", e);
            return null;
        }
    }

    /**
     * 转换营销的订单详情
     * 网关支付的交易没有调用批量计算手续费,使用特殊费率标识去营销获取商户及用户的营销
     *
     * @param orderDetailList    营销订单详情
     * @param mchntOrderInfoList 商户订单表
     */
    void convertOrderDetail(List<PaymentOrderDetailBean> orderDetailList, List<MchntOrderInfo> mchntOrderInfoList) {
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            PaymentOrderDetailBean paymentOrderDetailBean = new PaymentOrderDetailBean();
            paymentOrderDetailBean.setMchntNo(mchntOrderInfo.getMchntNo());
            if (mchntOrderInfo.getOrderDiscountAmt() != null && !mchntOrderInfo.getOrderDiscountAmt().isEmpty()) {
                paymentOrderDetailBean.setOrderAmt(AmountUtil.subtraction(mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getOrderDiscountAmt()));
            } else {
                paymentOrderDetailBean.setOrderAmt(mchntOrderInfo.getOrderAmt());
            }
            paymentOrderDetailBean.setMchntFeeReceivableRate(mchntOrderInfo.getFeeRate());
            paymentOrderDetailBean.setMchntSettleAmt(mchntOrderInfo.getRealSettleAmt());
            paymentOrderDetailBean.setMchntFeeReceivable(mchntOrderInfo.getMchntFee());
            paymentOrderDetailBean.setFeeInputMode("0");
            paymentOrderDetailBean.setFeeType("");
            paymentOrderDetailBean.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
            orderDetailList.add(paymentOrderDetailBean);
        }
    }

    /**
     * 解析营销合并支付调用结果
     *
     * @param userOrderInfo      用户订单表
     * @param mchntOrderInfoList 商户订单表
     * @param mompPayOrderInfo   营销支付订单表
     * @param mompResult         营销合并支付调用结果
     * @param channelCallCfg     通道服务调用配置
     * @param isCouponTrans      是否使用优惠劵
     * @throws Exception 异常
     */
    private void analysisMompResult(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo mompPayOrderInfo, Result<ComboPaymentResponse> mompResult,
                                    ChannelCallCfg channelCallCfg, boolean isCouponTrans, CupsGatewayPayRequest cupsGatewayPayRequest) throws Exception {
        String discountFlag = "N";
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderService orderService = new OrderServiceImpl();

        if (null == mompResult || !mompResult.isSuccess()) {
            if (isCouponTrans) {
                rglog.warn("使用卡劵交易调用营销失败,整个交易失败");
                updateOrderFail(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo);
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else {
                mompPayOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                mompPayOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                mompPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(null, null, mompPayOrderInfo)) {
                    rglog.warn("更新用户订单/商户订单信息失败");
                }
                rglog.debug("交易调用营销失败但未使用卡劵可继续进行交易");
                /*d0实时入账手续费四舍五入处理*/
                if (AppParamConstant.YES.equals(mchntOrderInfoList.get(0).getRealSettleFlag())) {
                    for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                        mchntOrderInfo.setMchntDiscountFee("0.00");
                        mchntOrderInfo.setRealMchntFee(AmountUtil.rounding(mchntOrderInfo.getRealMchntFee(), 2));
                        mchntOrderInfo.setMchntFee(AmountUtil.rounding(mchntOrderInfo.getMchntFee(), 2));
                        mchntOrderInfo.setMchntSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntOrderInfo.getRealMchntFee()));
                    }
                }
                return;
            }
        }

        ComboPaymentResponse mompResponse = mompResult.getResult();
        //营销调用超时，向营销系统异步发起冲正
        if (OpmsParamConstant.DUBBO_OVERTIME.equals(mompResponse.getRespCode())) {

            rglog.info("营销试算DUBBO接口-调用超时，发起冲正");
            mompRevsal(channelCallCfg);
            //更新用户订单表/商户订单表状态为失败
            updateOrderFail(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        } else if (!OpmsParamConstant.DUBBO_SUCCESS.equals(mompResponse.getRespCode())) {

            if (isCouponTrans) {
                rglog.error("使用卡劵交易调用营销失败,整个交易失败");
                updateOrderFail(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo);
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else {
                mompPayOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                mompPayOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                mompPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(null, null, mompPayOrderInfo)) {
                    rglog.warn("更新用户订单/商户订单信息失败");
                }
                rglog.debug("交易调用营销失败但未使用卡劵可继续进行交易");
                /*d0实时入账手续费四舍五入处理*/
                if (AppParamConstant.YES.equals(mchntOrderInfoList.get(0).getRealSettleFlag())) {
                    for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                        mchntOrderInfo.setMchntDiscountFee("0.00");
                        mchntOrderInfo.setRealMchntFee(AmountUtil.rounding(mchntOrderInfo.getRealMchntFee(), 2));
                        mchntOrderInfo.setMchntFee(AmountUtil.rounding(mchntOrderInfo.getMchntFee(), 2));
                        mchntOrderInfo.setMchntSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntOrderInfo.getRealMchntFee()));
                    }
                }
            }
        } else {

            //判断是否使用营销 参与营销，不实时入账
            if (AmountUtil.compare(mompResponse.getTransAmt(), mompResponse.getTxnAmt()) != 0) {
                discountFlag = AppParamConstant.YES;
            }

            //更新用户订单实际支付金额和优惠金额
            userOrderInfo.setRealPayAmt(mompResponse.getTxnAmt());
            userOrderInfo.setRealDiscountAmt(AmountUtil.subtraction(userOrderInfo.getOrderAmt(), mompResponse.getTxnAmt()));
            if (null != cupsGatewayPayRequest.getCouponInfo() && null != cupsGatewayPayRequest.getCouponInfo().getDiscountId()) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put(cupsGatewayPayRequest.getCouponInfo().getDiscountId(), cupsGatewayPayRequest.getCouponInfo().getDiscountAmt());
                userOrderInfo.setDiscountInfo(jsonObject.toJSONString());
            }

            ComboPaymentResponse comboPaymentResponse = mompResult.getResult();
            List<PaymentOrderDetailBean> orderDetailBeanList = comboPaymentResponse.getOrderDetailList();
            if (orderDetailBeanList == null || orderDetailBeanList.isEmpty()) {
                rglog.warn("营销返回数据有误，订单明细列表未返回。orderDetailBeanListSize:<{}>", orderDetailBeanList.size());
                updateOrderFail(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo);
                xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
                mompRevsal(channelCallCfg);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }

            //计算商户的优惠信息
            /*通道优惠金额累加*/
            String channelDiscountAmt = "0.00";
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {

                List<PaymentOrderDetailBean> paymentOrderDetailBeanList = orderDetailBeanList.stream().filter(item -> item.getMchntNo().equals(mchntOrderInfo.getMchntNo())).collect(Collectors.toList());
                if (paymentOrderDetailBeanList.isEmpty()) {
                    rglog.warn("当前商户无营销优惠信息，在订单明细列表中无当前商户数据。mchntNo:<{}>", mchntOrderInfo.getMchntNo());
                    updateOrderFail(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo);
                    xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
                    mompRevsal(channelCallCfg);
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }

                /*用户优惠金额(免充值优惠金额)*/
                String noRechargeAmt = "0.00";
                if ("0".equals(paymentOrderDetailBeanList.get(0).getMoneyOffSettlementMethod())) {
                    /*免充值需要减去商户满减补贴金额*/
                    noRechargeAmt = AmountUtil.addition(noRechargeAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyMchnt());
                } else {
                    channelDiscountAmt = AmountUtil.addition(channelDiscountAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal());
                }
                if ("0".equals(paymentOrderDetailBeanList.get(0).getCouponMchntSettleMethod())) {
                    /*免充值需要减去商户卡券补贴金额*/
                    noRechargeAmt = AmountUtil.addition(noRechargeAmt, paymentOrderDetailBeanList.get(0).getCouponMchntSubsidy());
                } else {
                    channelDiscountAmt = AmountUtil.addition(channelDiscountAmt, paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy());
                }
                rglog.debug("商户免充值金额:<{}>", noRechargeAmt);

                mchntOrderInfo.setRealSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), noRechargeAmt));
                //对客营销金额=商户免充值营销金额
                mchntOrderInfo.setCustomerMarketAmt(noRechargeAmt);
                if (paymentOrderDetailBeanList.get(0).getCouponNo() != null) {
                    mchntOrderInfo.setRedeemCouponIds(paymentOrderDetailBeanList.get(0).getCouponNo());
                }
                mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                //用户享受营销之后商户就不实时清算
                if (AppParamConstant.YES.equals(discountFlag)) {
                    rglog.info("当前用户享受营销,商户不支持实时清算");
                    mchntOrderInfo.setRealSettleFlag(OpmsParamConstant.OPMS_PARAM_NO);
                }
            }

            /*营销系统返回成功，更新订单支付订单状态为成功*/
            mompPayOrderInfo.setChannelDiscountAmt(channelDiscountAmt);
            mompPayOrderInfo.setSettleDate(DateUtil.getCurrentDate());
            mompPayOrderInfo.setRespCode(mompResult.getResult().getRespCode());
            mompPayOrderInfo.setRespDesc(mompResult.getResult().getRespDesc());
            mompPayOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            mompPayOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            mompPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo)) {
                rglog.warn("更新用户/商户/营销支付订单表失败");
            }
        }

        //是否使用优惠标识存入节点内
        if (AppParamConstant.NO.equals(discountFlag)) {
            xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.NO);
        } else {
            xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
        }
    }

    /**
     * 登记新网银支付订单表
     *
     * @param request       请求体
     * @param userOrderInfo 用户订单
     * @return 支付订单
     * @throws Exception 异常
     */
    private PayOrderInfo registPayOrderInfo(CupsGatewayPayRequest request, UserOrderInfo userOrderInfo, ChannelCallCfg channelCallCfg) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        MchntAcctInfo mchntAcctInfo = (MchntAcctInfo) xmlTreeUtil.getXmlTreeObjectValue(OpmsTreeNodeConstant.MCHNT_ACCT_INFO, MchntAcctInfo.class);

        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        payOrderInfo.setTxnTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        payOrderInfo.setTxnNum(request.getHeader().getTxnNum());
        payOrderInfo.setBizType(request.getHeader().getBizType());
        payOrderInfo.setRealPayAmt(userOrderInfo.getRealPayAmt());
        payOrderInfo.setPayType(PayTypeEnum.OTHER_BANK_CARD.getPayType());
        payOrderInfo.setPayerAcctType("");
        payOrderInfo.setPayeeAcctType(mchntAcctInfo.getSettleAcctType());
        payOrderInfo.setPayeeAcctInfo(mchntAcctInfo.getSettleAcctNo());
        payOrderInfo.setSysSeqNum(sysSeqNum);
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setDstChannelType(ChannelEnum.UPGW.getChannelType());
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setChannelSeqNum("");
        payOrderInfo.setChannelReconKey(GlobalEsbUtil.generateEsbSeqeuenceNumber(request.getHeader().getInstId()));
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        //使用备用字段1 放入网关渠道标识,退款的时候从当前字段取值
        payOrderInfo.setRemark1(request.getGatewayChanlId());
        OrderService orderService = new OrderServiceImpl();
        if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
            rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        } else {
            rglog.debug("登记支付订单表成功,payOrderInfo:<{}>", JSON.toJSONString(payOrderInfo));
        }
        return payOrderInfo;
    }

    /**
     * 新网银个人网关全额消费调用
     *
     * @param request        请求体
     * @param userOrderInfo  用户订单
     * @param channelCallCfg 个人全额消费通道服务调用配置
     * @return 个人网关全额消费应答
     * @throws Exception 异常
     */
    private UpgwPersonalGatewayPaymentResponse cupsGatewayPersonalPay(CupsGatewayPayRequest request, UserOrderInfo userOrderInfo, PayOrderInfo upgwPayOrderInfo,
                                                                      List<MchntOrderInfo> mchntOrderInfoList, ChannelCallCfg channelCallCfg, ChannelCallCfg mompChannelCallCfg) throws Exception {

        //获取商户基本信息
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(request.getHeader().getInstId(), mchntOrderInfoList.get(0).getMchntNo());
        String mchntName;
        if (null == mchntInfo) {
            PlatMchntInfo platMchntInfo = mchntService.getPlatMchntInfo(request.getHeader().getInstId(), request.getPlatMchntNo());
            mchntName = platMchntInfo.getPlatMchntName();
        } else {
            mchntName = mchntInfo.getMchntName();
        }

        /*获取银联商户号*/
        if (mchntInfo == null) {
            rglog.error("商户未开通银联业务，不支持银联token支付");
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(mompChannelCallCfg);
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }

        /*获取银联机构号*/
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam ncqsInstCodeParam = sysParamService.getSysParamInfo(request.getHeader().getInstId(), OpmsParamConstant.OPMS_SYS_PARAM, OpmsParamConstant.NCQS_INST_CODE);
        if (null == ncqsInstCodeParam || AppParamConstant.NO.equals(ncqsInstCodeParam.getParamStatus())) {
            rglog.warn("机构为设置无卡快捷银联机构号，instId:<{}>", request.getHeader().getInstId());
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(channelCallCfg);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        /*获取后台通知地址*/
        SysParam backNoticeUrlSysParam = sysParamService.getSysParamInfo(request.getHeader().getInstId(), OpmsParamConstant.UPAC_CONF_NODE, OpmsParamConstant.UPAC_BANK_URL);
        if (null == backNoticeUrlSysParam) {
            rglog.info("机构全渠道后台通知地址未配置,instId:<{}>", request.getHeader().getInstId());
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(channelCallCfg);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        /*
         * 根据上送的渠道标识获取终端类型和商户交易来源
         * WEB渠道上来的 终端类型认定为 电脑-07，商户交易来源认定为 电脑浏览器-01
         * 其他渠道上来 终端类型认定为 手机-08，商户交易来源认定为 手机浏览器-02
         */
        String termType;
        String mchntTransSource;
        rglog.debug("交易渠道标识:<{}>", request.getHeader().getChanlId());
        if (OpmsParamConstant.OPMS_WEB.equals(request.getHeader().getChanlId())) {
            termType = "07";
            mchntTransSource = "01";
        } else {
            termType = "08";
            mchntTransSource = "02";
        }

        //个人网银支付请求头
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        cc.rengu.igas.channel.upgw.facade.base.Header header = new cc.rengu.igas.channel.upgw.facade.base.Header();
        header.setInstId(request.getHeader().getInstId());
        header.setVersion("1.0.0");
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
        header.setBizType(OpmsParamConstant.DUBBO_DEFAULT_BIZ_TYPE);
        header.setTxnNum(channelCallCfg.getCallChannelTxn());
        header.setTraceNo(upgwPayOrderInfo.getChannelReconKey());
        header.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        header.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));

        //终端信息
        TermInfo termInfo = new TermInfo();
        termInfo.setTermType(termType);
        //商户信息
        UpgwMchntInfo upgwMchntInfo = new UpgwMchntInfo();
        upgwMchntInfo.setMchntNo(mchntInfo.getCupsMchntNo());
        upgwMchntInfo.setMchntType(mchntInfo.getIndustryType());
        upgwMchntInfo.setMchntName(mchntName);
        upgwMchntInfo.setMchntTransSource(mchntTransSource);
        //风险信息
        RiskInfo riskInfo = new RiskInfo();
        ConvertUtil.convertOutput(riskInfo);
        /*
         * 个人网银支付请求体
         * 业务类型 100003-实物消费
         * 业务功能类型 111011-全额消费
         */
        UpgwPersonalGatewayPaymentRequest upgwPersonalReqeust = new UpgwPersonalGatewayPaymentRequest();
        upgwPersonalReqeust.setBusiType("100003");
        //upgwPersonalReqeust.setBusiFuncType("111011");
        upgwPersonalReqeust.setProductType("");
        upgwPersonalReqeust.setProductAssInfo("");
        upgwPersonalReqeust.setOrderAmt(userOrderInfo.getRealPayAmt());
        upgwPersonalReqeust.setPayerIssrChannelId(request.getGatewayChanlId());
        upgwPersonalReqeust.setPayerLimitAcctType(xmlTreeUtil.getXmlTreeStringValue("LmtAcctTpCd"));
        upgwPersonalReqeust.setPayerAcctName("");
        upgwPersonalReqeust.setPayerCertType("");
        upgwPersonalReqeust.setPayerCertNo("");
        upgwPersonalReqeust.setOriIssrId(ncqsInstCodeParam.getParamValue());
        upgwPersonalReqeust.setPayeeAcctInfo("");
        upgwPersonalReqeust.setPayeeAcctName("");
        upgwPersonalReqeust.setPayeeAreaCode("");
        upgwPersonalReqeust.setPayeeBackUrl(request.getFrontBackUrl());
        upgwPersonalReqeust.setOrderId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        upgwPersonalReqeust.setOrderDesc("");
        upgwPersonalReqeust.setTermInfo(termInfo);
        upgwPersonalReqeust.setMchntInfo(upgwMchntInfo);
        upgwPersonalReqeust.setRiskInfo(riskInfo);
        upgwPersonalReqeust.setHeader(header);
        //调用个人网关支付接口
        DubboService dubboService = new DubboServiceImpl();
        cc.rengu.igas.channel.upgw.facade.result.Result<UpgwPersonalGatewayPaymentResponse> responseResult;
        try {
            responseResult = (cc.rengu.igas.channel.upgw.facade.result.Result<UpgwPersonalGatewayPaymentResponse>) dubboService.callDubboService(OpmsParamConstant.DUBBO_UPGW_SERVICE, "upgwPersonalGatewayPayment", upgwPersonalReqeust);
        } catch (Exception e) {
            rglog.error("调用新网银个人网关支付异常:<{}>", e);
            responseResult = null;
        }

        //判断调用结果成功还是失败
        if (null == responseResult || !responseResult.isSuccess()) {
            rglog.warn("调用新网银个人网关支付失败，响应结果为空");
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(channelCallCfg);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        } else if (!OpmsParamConstant.DUBBO_RECV_SUCCESS.equals(responseResult.getResult().getRespCode())) {
            rglog.warn("调用新网银个人网关支付失败，respCode:<{}>,respDesc:<{}>",
                    responseResult.getResult().getRespCode(), responseResult.getResult().getRespDesc());
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(channelCallCfg);
            throw new BizException(responseResult.getResult().getRespCode(), responseResult.getResult().getRespDesc());
        }

        return responseResult.getResult();
    }

    /**
     * 解析个人网银调用结果
     *
     * @param upgwPersonalResponse 个人网银调用返回信息
     * @return 响应前端信息
     */
    private CupsGatewayPayResponse analysisUpgwPersonalResponse(UpgwPersonalGatewayPaymentResponse upgwPersonalResponse) {

        //加密信息
        EncryptAssInfo encryptAssInfo = new EncryptAssInfo();
        encryptAssInfo.setEncryptSignSn(upgwPersonalResponse.getEncryptAssInfo().getSignCertSn());
        encryptAssInfo.setEncryptEncSn(upgwPersonalResponse.getEncryptAssInfo().getEncyCertSn());
        encryptAssInfo.setEncryptEncKey(upgwPersonalResponse.getEncryptAssInfo().getEncyKey());
        encryptAssInfo.setEncryptSignEncAlgoType(upgwPersonalResponse.getEncryptAssInfo().getSignEncyAlgo());
        encryptAssInfo.setEncryptMDAlgoType(upgwPersonalResponse.getEncryptAssInfo().getMdAlgoType());
        encryptAssInfo.setEncryptEncAlgoType(upgwPersonalResponse.getEncryptAssInfo().getEncyAlgoType());
        /*
         * 响应信息
         * 业务类型 100003-实物消费
         * 业务功能类型 111011-全额消费
         * 网关交易类型 1005-个人网关支付
         * 版本号默认 1000
         */
        CupsGatewayPayResponse cupsGatewayPayResponse = new CupsGatewayPayResponse();
        cupsGatewayPayResponse.setGatewayBizType("100003");
        cupsGatewayPayResponse.setGatewayBizFunc("111011");
        cupsGatewayPayResponse.setGatewayTransType("1005");
        cupsGatewayPayResponse.setGatewayUrl(upgwPersonalResponse.getPayerIssrChannelUrl());
        cupsGatewayPayResponse.setGatewayChanlId(upgwPersonalResponse.getPayerIssrChannelId());
        cupsGatewayPayResponse.setEncryptMsg(upgwPersonalResponse.getEncryptAssInfo().getEncyMsg());
        cupsGatewayPayResponse.setGatewayVersion("1000");
        cupsGatewayPayResponse.setEncryptAssInfo(encryptAssInfo);
        return cupsGatewayPayResponse;
    }


    /**
     * 新网银企业网关全额消费调用
     *
     * @param request        请求体
     * @param userOrderInfo  用户订单
     * @param channelCallCfg 个人全额消费通道服务调用配置
     * @return 个人网关全额消费应答
     * @throws Exception 异常
     */
    private UpgwEnterpriseGatewayPaymentResponse cupsGatewayEnterprisePay(CupsGatewayPayRequest request, UserOrderInfo userOrderInfo, PayOrderInfo upgwPayOrderInfo,
                                                                          List<MchntOrderInfo> mchntOrderInfoList, ChannelCallCfg channelCallCfg, ChannelCallCfg mompChannelCallCfg) throws Exception {

        //获取商户基本信息
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(request.getHeader().getInstId(), mchntOrderInfoList.get(0).getMchntNo());
        String mchntName;
        if (null == mchntInfo) {
            PlatMchntInfo platMchntInfo = mchntService.getPlatMchntInfo(request.getHeader().getInstId(), request.getPlatMchntNo());
            mchntName = platMchntInfo.getPlatMchntName();
        } else {
            mchntName = mchntInfo.getMchntName();
        }

        /*获取商户结算信息*/
        List<MchntAcctInfo> mchntAcctInfoList;
        mchntAcctInfoList = mchntService.getMchntAcctInfo(request.getHeader().getInstId(), request.getPlatMchntNo());
        Optional<MchntAcctInfo> mchntAcctInfoOpt = mchntAcctInfoList.stream().filter(item -> item.getFundType().equals("00")).findFirst();
        if (!mchntAcctInfoOpt.isPresent()) {
            rglog.warn("商户结算账户信息不存在，交易终止");
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(mompChannelCallCfg);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        /*获取银联商户号*/
        if (mchntInfo == null) {
            rglog.error("商户未开通银联业务，不支持银联token支付");
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(mompChannelCallCfg);
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }

        /*获取银联机构号*/
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam ncqsInstCodeParam = sysParamService.getSysParamInfo(request.getHeader().getInstId(), OpmsParamConstant.OPMS_SYS_PARAM, OpmsParamConstant.NCQS_INST_CODE);
        if (null == ncqsInstCodeParam || AppParamConstant.NO.equals(ncqsInstCodeParam.getParamStatus())) {
            rglog.warn("机构为设置无卡快捷银联机构号，instId:<{}>", request.getHeader().getInstId());
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(channelCallCfg);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        /*获取后台通知地址*/
        SysParam backNoticeUrlSysParam = sysParamService.getSysParamInfo(request.getHeader().getInstId(), OpmsParamConstant.UPAC_CONF_NODE, OpmsParamConstant.UPAC_BANK_URL);
        if (null == backNoticeUrlSysParam) {
            rglog.info("机构全渠道后台通知地址未配置,instId:<{}>", request.getHeader().getInstId());
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(channelCallCfg);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        /*
         * 根据上送的渠道标识获取终端类型和商户交易来源
         * WEB渠道上来的 终端类型认定为 电脑-07，商户交易来源认定为 电脑浏览器-01
         * 其他渠道上来 终端类型认定为 手机-08，商户交易来源认定为 手机浏览器-02
         */
        String termType;
        String mchntTransSource;
        rglog.debug("交易渠道标识:<{}>", request.getHeader().getChanlId());
        if (OpmsParamConstant.OPMS_WEB.equals(request.getHeader().getChanlId())) {
            termType = "07";
            mchntTransSource = "01";
        } else {
            termType = "08";
            mchntTransSource = "02";
        }

        //个人网银支付请求头
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        cc.rengu.igas.channel.upgw.facade.base.Header header = new cc.rengu.igas.channel.upgw.facade.base.Header();
        header.setInstId(request.getHeader().getInstId());
        header.setVersion("1.0.0");
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
        header.setBizType(OpmsParamConstant.DUBBO_DEFAULT_BIZ_TYPE);
        header.setTxnNum(channelCallCfg.getCallChannelTxn());
        header.setTraceNo(upgwPayOrderInfo.getChannelReconKey());
        header.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        header.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));

        //终端信息
        TermInfo termInfo = new TermInfo();
        termInfo.setTermType(termType);
        //商户信息
        UpgwMchntInfo upgwMchntInfo = new UpgwMchntInfo();
        upgwMchntInfo.setMchntNo(mchntInfo.getCupsMchntNo());
        upgwMchntInfo.setMchntType(mchntInfo.getIndustryType());
        upgwMchntInfo.setMchntName(mchntName);
        upgwMchntInfo.setMchntTransSource(mchntTransSource);
        //风险信息
        RiskInfo riskInfo = new RiskInfo();
        ConvertUtil.convertOutput(riskInfo);
        /*
         * 企业网银支付请求体
         * 业务类型 100003-实物消费
         * 业务功能类型 111011-全额消费
         */
        UpgwEnterpriseGatewayPaymentRequest upgwEnterpriseRequest = new UpgwEnterpriseGatewayPaymentRequest();
        upgwEnterpriseRequest.setBusiType("100003");
        //upgwPersonalReqeust.setBusiFuncType("111011");
        upgwEnterpriseRequest.setProductType("");
        upgwEnterpriseRequest.setProductAssInfo("");
        upgwEnterpriseRequest.setOrderAmt(userOrderInfo.getRealPayAmt());
        upgwEnterpriseRequest.setPayerIssrChannelId(request.getGatewayChanlId());
        upgwEnterpriseRequest.setOriIssrId(ncqsInstCodeParam.getParamValue());
        upgwEnterpriseRequest.setPayeeAcctInfo(mchntAcctInfoOpt.get().getSettleAcctNo());
        upgwEnterpriseRequest.setPayeeAcctName(mchntAcctInfoOpt.get().getSettleAcctName());
        upgwEnterpriseRequest.setPayeeOpenBankNo(mchntAcctInfoOpt.get().getSettleAcctBankNo());
        upgwEnterpriseRequest.setPayeeOpenBankName(mchntAcctInfoOpt.get().getSettleAcctBankName());
        upgwEnterpriseRequest.setPayeeBackUrl(request.getFrontBackUrl());
        upgwEnterpriseRequest.setOrderId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        upgwEnterpriseRequest.setOrderDesc("");
        upgwEnterpriseRequest.setTermInfo(termInfo);
        upgwEnterpriseRequest.setMchntInfo(upgwMchntInfo);
        upgwEnterpriseRequest.setRiskInfo(riskInfo);
        upgwEnterpriseRequest.setHeader(header);
        //调用个人网关支付接口
        DubboService dubboService = new DubboServiceImpl();
        cc.rengu.igas.channel.upgw.facade.result.Result<UpgwEnterpriseGatewayPaymentResponse> responseResult;
        try {
            responseResult = (cc.rengu.igas.channel.upgw.facade.result.Result<UpgwEnterpriseGatewayPaymentResponse>) dubboService.callDubboService(OpmsParamConstant.DUBBO_UPGW_SERVICE, "upgwEnterpriseGatewayPayment", upgwEnterpriseRequest);
        } catch (Exception e) {
            rglog.error("调用新网银企业网关支付异常:<{}>", e);
            responseResult = null;
        }

        //判断调用结果成功还是失败
        if (null == responseResult || !responseResult.isSuccess()) {
            rglog.warn("调用新网银企业网关支付失败，响应结果为空");
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(channelCallCfg);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        } else if (!OpmsParamConstant.DUBBO_RECV_SUCCESS.equals(responseResult.getResult().getRespCode())) {
            rglog.warn("调用新网银企业网关支付失败，respCode:<{}>,respDesc:<{}>",
                    responseResult.getResult().getRespCode(), responseResult.getResult().getRespDesc());
            updateOrderFail(userOrderInfo, mchntOrderInfoList, upgwPayOrderInfo);
            mompRevsal(channelCallCfg);
            throw new BizException(responseResult.getResult().getRespCode(), responseResult.getResult().getRespDesc());
        }

        return responseResult.getResult();
    }

    /**
     * 解析企业网银调用结果
     *
     * @param upgwEnterpriseResponse 企业网银调用返回信息
     * @return 响应前端信息
     */
    private CupsGatewayPayResponse analysisUpgwEnterpriseResponse(UpgwEnterpriseGatewayPaymentResponse upgwEnterpriseResponse) {

        //加密信息
        EncryptAssInfo encryptAssInfo = new EncryptAssInfo();
        encryptAssInfo.setEncryptSignSn(upgwEnterpriseResponse.getEncryptAssInfo().getSignCertSn());
        encryptAssInfo.setEncryptEncSn(upgwEnterpriseResponse.getEncryptAssInfo().getEncyCertSn());
        encryptAssInfo.setEncryptEncKey(upgwEnterpriseResponse.getEncryptAssInfo().getEncyKey());
        encryptAssInfo.setEncryptSignEncAlgoType(upgwEnterpriseResponse.getEncryptAssInfo().getSignEncyAlgo());
        encryptAssInfo.setEncryptMDAlgoType(upgwEnterpriseResponse.getEncryptAssInfo().getMdAlgoType());
        encryptAssInfo.setEncryptEncAlgoType(upgwEnterpriseResponse.getEncryptAssInfo().getEncyAlgoType());
        /*
         * 响应信息
         * 业务类型 100003-实物消费
         * 业务功能类型 111011-全额消费
         * 网关交易类型 1011-企业网关支付
         * 版本号默认 1000
         */
        CupsGatewayPayResponse cupsGatewayPayResponse = new CupsGatewayPayResponse();
        cupsGatewayPayResponse.setGatewayBizType("100003");
        cupsGatewayPayResponse.setGatewayBizFunc("111011");
        cupsGatewayPayResponse.setGatewayTransType("1011");
        cupsGatewayPayResponse.setGatewayUrl(upgwEnterpriseResponse.getPayerIssrChannelUrl());
        cupsGatewayPayResponse.setGatewayChanlId(upgwEnterpriseResponse.getPayerIssrChannelId());
        cupsGatewayPayResponse.setEncryptMsg(upgwEnterpriseResponse.getEncryptAssInfo().getEncyMsg());
        cupsGatewayPayResponse.setGatewayVersion("1000");
        cupsGatewayPayResponse.setEncryptAssInfo(encryptAssInfo);
        return cupsGatewayPayResponse;
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        Optional<ChannelCallCfg> channelCallCfgOpt = channelCallCfgList.stream().filter(item ->
                item.getBizScene().equals(ShareParamConstant.CALL_CFG_DEFAULT_BIZ_SCENE)).findFirst();
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        return transStatusEnum;
    }
}
